package de.johanngehrisch.pacecalc.model;

public class PaceCalculator {

	public class CalcMode  {
		public final static int pace = 0;
		public final static int duration = 1;
		public final static int distance = 2;
	}

	public class DistanceUnit {
		public final static int kilometer = 0;
		public final static int miles = 1;
	}

	public class PaceUnit {
		public final static int minutesPerKilometer = 0;
		public final static int minutesPerMile = 1;
		public final static int kilometersPerHour = 2;
		public final static int milesPerHour = 3;
	}

	private static final float mileInKilometer = 1.609344f;

	/**
	 * Calculates one of the following parameters based on the third one. The
	 * result parameter is configured through the parameter calcMode.
	 * 
	 * 
	 * @param calcMode
	 *            sets, whether the pace, the duration or the distance should be
	 *            calculated
	 * @param param1
	 *            for the calcModes pace and duration, this parameter is the
	 *            distance, for the calcMode distance this parameter is the
	 *            duration in seconds
	 * @param param2
	 *            for the calcModes duration and distance, this parameter is the
	 *            pace in seconds, for the calcMode pace it is the duration in
	 *            seconds
	 * @return depending on the calcMode one of the following: the pace (in
	 *         seconds), the duration (in seconds) or the distance
	 */
	public static float calculatePace(int calcMode, float param1,
			float param2, int du, int pu) {

		switch (calcMode) {
		case CalcMode.pace:
			return toPace(param2 / fromDistance(param1, du), pu);
		case CalcMode.duration:
			return fromDistance(param1, du) * fromPace(param2, pu);
		case CalcMode.distance:
			return toDistance(param1 / fromPace(param2, pu), du);
		}

		return 0;
	}

	private static float fromPace(float pace, int pu) {
		
		switch (pu) {
		case PaceUnit.kilometersPerHour:
			return (1 / pace) * 3600;
		case PaceUnit.milesPerHour:
			return (1 / pace) * 3600 / mileInKilometer;
		case PaceUnit.minutesPerMile:
			return pace / mileInKilometer;
		case PaceUnit.minutesPerKilometer:
			return pace;
		}

		return pace;
	}

	private static float toPace(float pace, int pu) {
		switch (pu) {
		case PaceUnit.kilometersPerHour:
			return (1 / pace) * 3600;
		case PaceUnit.milesPerHour:
			return (1 / pace) * 3600 / mileInKilometer;
		case PaceUnit.minutesPerMile:
			return pace * mileInKilometer;
		case PaceUnit.minutesPerKilometer:
			return pace;
		}

		return pace;
	}

	private static float fromDistance(float distance, int du) {
		switch (du) {
		case DistanceUnit.miles:
			return distance * mileInKilometer;

		case DistanceUnit.kilometer:
			return distance;
		}

		return distance;
	}

	private static float toDistance(float distance, int du) {
		switch (du) {
		case DistanceUnit.miles:
			return distance / mileInKilometer;

		case DistanceUnit.kilometer:
			return distance;
		}

		return distance;
	}

	public static float convertDistance(float distance, int from,
			int to) {
		return toDistance(fromDistance(distance, from), to);
	}

	public static float convertPace(float pace, int from, int to) {
		System.out.println("convertPace("+pace+", "+from+", "+to+") :: "+toPace(fromPace(pace, from), to)+" via "+fromPace(pace, from));
		return toPace(fromPace(pace, from), to);
	}

}
